﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Common.Core;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace Common.Unity
{
	public class UnityContainerConfigurationCreator
	{
		const string UnityName = "unity";
		readonly string configurationFilePath;
		readonly string configurationSectionName;

		public UnityContainerConfigurationCreator() : this( null, UnityName )
		{}

		public UnityContainerConfigurationCreator( string configurationFilePath ) : this( configurationFilePath, UnityName )
		{}

		public UnityContainerConfigurationCreator( string configurationFilePath, string configurationSectionName )
		{
			this.configurationFilePath = configurationFilePath;
			this.configurationSectionName = configurationSectionName;
		}

		public UnityContainer Create()
		{
			var result = Create<UnityContainer>( null );
			return result;
		}

		public UnityContainer Create( string containerName )
		{
			var result = Create<UnityContainer>( containerName );
			return result;
		}

		public ContainerType Create<ContainerType>( string containerName ) where ContainerType : IUnityContainer, new()
		{
			var result = new ContainerType();
			result.RegisterInstance<IUnityContainer>( result );
			using ( ThreadLocalStorage.Push<IUnityContainer>( result ) )
			{
				var element = ResolveConfiguration( containerName );
				if ( element != null )
				{
					element.Configure( result );
				}
			}
			return result;
		}

		UnityContainerElement ResolveConfiguration( string name )
		{
			var section = ResolveSection();
			if ( section != null )
			{
				var element = !string.IsNullOrEmpty( name ) ? section.Containers[ name ] : section.Containers.Default;
				if ( element != null )
				{
					return element;
				}
			}
			return null;
		}

        UnityConfigurationSection ResolveSection()
        {
			if ( !string.IsNullOrEmpty( configurationFilePath ) )
			{
	            var map = new ExeConfigurationFileMap
                      	{
                      		ExeConfigFilename = configurationFilePath
                      	};
				var configuration = ConfigurationManager.OpenMappedExeConfiguration( map, ConfigurationUserLevel.None );
				var result = (UnityConfigurationSection)configuration.GetSection( UnityName );
				return result;
			}
        	return ConfigurationManager.GetSection( configurationSectionName ) as UnityConfigurationSection;
        }

	}
}
